/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       sanctuary.cpp

	$Header: /game/sanctuary.cpp $

	$NoKeywords: $

 ************************************************************************/

#include "precompiled.h"
#include "sanctuary.h"

#include "adaptor_handler.h"
#include "adventure_frame.h"
#include "adventure_map.h"
#include "adventure_sounds.h"
#include "army.h"
#include "basic_dialog.h"
#include "bitmap_group.h"
#include "bitmap_group_cache.h"
#include "bitmap_layer_window.h"
#include "bound_handler.h"
#include "button.h"
#include "button_cache.h"
#include "dialog_resurrect.h"
#include "external_string.h"
#include "hero.h"
#include "music.h"
#include "object_registration.h"
#include "mouse_event.h"
#include "player.h"
#include "resurrect_heroes.h"
#include "simple_dialog.h"
#include "standard_fonts.h"

// ------------------------------------------------------------------------
// sanctuary dialog
// ------------------------------------------------------------------------
namespace
{
	int const k_current_save_version = 3;


	enum
	{
		k_choice_cancel,
		k_choice_enter,
		k_choice_resurrect
	};

	class t_dialog_sanctuary : public t_window
	{
	public:
		t_dialog_sanctuary( t_window* parent );

		void enable_entry( bool arg );
		void set_text( std::string const& text );
		void set_title( std::string const& title );
	protected:
		void close_click( t_button* button, int value );

		t_bitmap_group_ptr	m_bitmaps;
		t_button*			m_enter_button;
		t_text_window*		m_text;
		t_text_window*		m_title;
	};


	t_object_registration< t_sanctuary > k_registration( k_adv_object_sanctuary );
	t_object_registration< t_sea_sanctuary > k_sea_sanctuary_registration( k_adv_object_port );
};



// ------------------------------------------------------------------------
// sanctuary for armies - heal, resurrect, remain safe from harm
// ------------------------------------------------------------------------
t_sanctuary::t_sanctuary( std::string const& source )
           : t_owned_adv_object( source )
{
	memset( m_paid, 0, sizeof( m_paid ) );
}

// ------------------------------------------------------------------------
// sanctuary for armies - heal, resurrect, remain safe from harm
// ------------------------------------------------------------------------
static int const k_rental_fee = 200;

static t_external_string const k_text_sanctuary_resurrects_heroes( "sanctuary_resurrects_heroes.misc" );
void t_sanctuary::activate_trigger( t_army* army, t_adv_map_point const& point, 
									t_direction direction, 
									t_adventure_frame* frame )
{
	t_dialog_sanctuary*				dialog;
	t_player*						player = army->get_owner();
	std::string						text;
	t_screen_point					zero(0,0);

	resurrect_heroes( *army, k_text_sanctuary_resurrects_heroes, frame );
	dialog = new t_dialog_sanctuary( frame );

	if (!empty())
	{
		dialog->set_text( get_text( "denied" ) );
		dialog->enable_entry( false );
	}
	else if (m_paid[army->get_owner_number()])
	{
		dialog->set_text( get_text( "paid" ) );
		dialog->enable_entry( true );
	}
	else
	{
		dialog->set_text( get_text( "initial" ));
		dialog->enable_entry( player->get_funds()[k_gold] >= k_rental_fee);
	}
	dialog->set_title( get_name() );

	t_sound_cache music = get_music_playing();
	stop_music();
	get_dialog_sound( k_dialog_sound_sanctuary )->play( get_sound_volume() );
	switch (dialog->run_modal())
	{
		case k_choice_cancel:
			return;

		case k_choice_enter:
			if (!m_paid[army->get_owner_number()])
			{
				player->spend( k_gold, k_rental_fee );
				m_paid[army->get_owner_number()] = true;
			}
			set_owner( army->get_owner_number() );
			swap( army->get_creatures() );
			frame->destroy_army( army );
			break;
	}
	play_music( music );
}

bool t_sanctuary::is_triggered_by( t_creature_array const& army ) const
{
	return !army.is_boat();
}

// ------------------------------------------------------------------------
// sanctuary for armies - heal, resurrect, remain safe from harm
// ------------------------------------------------------------------------
int t_sanctuary::get_version() const
{
	return k_current_save_version;
}

// ------------------------------------------------------------------------
// sanctuary for armies - heal, resurrect, remain safe from harm
// ------------------------------------------------------------------------
void t_sanctuary::dump_visitors()
{
	t_adv_map_point point;

	if (!find_adjacent_space( point, *this ))
		return;
	
	t_army_ptr army;

	army = new t_army( this );
	army->set_owner( get_owner_number() );
	army->place( *m_map, point );
	set_owner( -1 );
	get_adventure_frame()->select_army( army );
	get_adventure_frame()->update();
	army->trigger_events();
}

// ------------------------------------------------------------------------
// sanctuary for armies - heal, resurrect, remain safe from harm
// ------------------------------------------------------------------------
void t_sanctuary::process_new_day()
{
	if (!empty() && !m_paid[get_owner_number()])
	{
		t_player* player;

		player = get_owner();
		if (player->get_funds()[k_gold] < k_rental_fee)
			dump_visitors();
		else
			player->spend( k_gold, k_rental_fee );
	}
	memset( m_paid, 0, sizeof(m_paid));
	if (empty())
		return;

	t_creature_array::process_new_day( false );
	t_owned_adv_object::process_new_day();

	int     i;
	t_hero* hero;

	for (i = 0; i < t_creature_array::k_size; i++)
	{
		hero = (*this)[i].get_hero();
		if (hero == 0)
			continue;
		if (!hero->is_dead())
			hero->set_wounds( 0 );
	}
}

// ------------------------------------------------------------------------
// sanctuary for armies - heal, resurrect, remain safe from harm
// ------------------------------------------------------------------------
void t_sanctuary::left_double_click( t_mouse_event const& event, 
							           t_adventure_frame* frame )
{
	if (get_owner_number() != m_map->get_player_number())
		return;
	if (empty())
		return;
	if (!yes_no_dialog( get_text( "exit" ) ))
		return;
	dump_visitors();
}

// ------------------------------------------------------------------------
// sanctuary for armies - heal, resurrect, remain safe from harm
// ------------------------------------------------------------------------
bool t_sanctuary::read( std::streambuf&						stream, 
						t_qualified_adv_object_type const&	type,
						int									version )
{
	if (version < 1)
		return true;
	t_owned_adv_object::read( stream, type, version );
	::read( stream, &m_paid, sizeof( m_paid ));

	// -------------------------------------------------------------------
	// Translate t_sanctuary's save file version to t_creature_array's version
	// -------------------------------------------------------------------
	if (version <= 1)
		return t_creature_array::read_version( stream, 0 );
	if (version < 3)
		return t_creature_array::read_version( stream, 1 );
	return t_creature_array::read( stream );
}

// ------------------------------------------------------------------------
// sanctuary for armies - heal, resurrect, remain safe from harm
// ------------------------------------------------------------------------
void t_sanctuary::right_click( t_mouse_event const& event,
		                         t_adventure_frame* adventure_frame )
{
	if (!empty())
		show_popup_text( get_text( "help_full" ), event.screen_point );
	else
		show_popup_text( get_text( "help" ), event.screen_point );
}

// ------------------------------------------------------------------------
// sanctuary for armies - heal, resurrect, remain safe from harm
// ------------------------------------------------------------------------
bool t_sanctuary::write( std::streambuf& stream ) const
{
	t_owned_adv_object::write( stream );
	::write( stream, &m_paid, sizeof( m_paid ));
	return t_creature_array::write( stream );
}

// ------------------------------------------------------------------------
// sanctuary for armies - heal, resurrect, remain safe from harm
// ------------------------------------------------------------------------
int t_sanctuary::compute_scouting_range() const
{
	int base_range = t_owned_adv_object::compute_scouting_range();
	int creature_range = t_creature_array::compute_scouting_range();
	if ( creature_range > base_range )
		return creature_range;
	return base_range;
}

// ------------------------------------------------------------------------
// Called after read_from_map
// ------------------------------------------------------------------------
void t_sanctuary::initialize( t_adventure_map& map )
{
	t_owned_adv_object::initialize( map );
	t_creature_array::initialize();
}

// --------------------------------------------------------------
// Cannot delete sanctuaries (might kill the army)
// --------------------------------------------------------------
bool t_sanctuary::is_deleted_by_deletion_marker() const
{
	return false;
}


// ------------------------------------------------------------------------
// Called after read
// ------------------------------------------------------------------------
void t_sanctuary::read_postplacement( t_adventure_map& map )
{
	t_owned_adv_object::read_postplacement( map );
	t_creature_array::read_postplacement( map );
}

// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
void t_sanctuary::on_begin_turn()
{
	t_creature_array::on_begin_turn();
	t_owned_adv_object::on_begin_turn();
}

// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
void t_sanctuary::on_end_turn()
{
	t_creature_array::on_end_turn();
	t_owned_adv_object::on_end_turn();
}

// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
void t_sanctuary::set_owner( int player_number )
{
	if (get_owner() != 0)
		get_owner()->remove( this );

	t_owned_adv_object::set_owner( player_number );
	
	if (get_owner() != 0)
		get_owner()->add( this );
}

void t_sanctuary::place( t_adventure_map& map, t_adv_map_point const& point )
{
	t_owned_adv_object::place( map, point );

	if (get_owner_number() >= 0)
		get_owner()->add( this );
}


// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
t_skill_mastery t_sanctuary::get_anti_stealth_level() const
{
	return t_creature_array::get_anti_stealth_level();
}

// ------------------------------------------------------------------------
// sanctuary dialog
// ------------------------------------------------------------------------
static t_bitmap_group_cache const k_layout( "dialog.sanctuary" );
static t_external_string const		k_text_resurrect_label( "sanctuary_resurrect.misc" );
static t_external_string const		k_text_entry_label( "sanctuary_entry.misc" );
extern t_button_cache const		k_close_button;

t_dialog_sanctuary::t_dialog_sanctuary( t_window* parent )
                  : t_window( k_completely_transparent, parent )
{
	t_screen_rect rect;

	m_bitmaps = k_layout.get();
	rect = m_bitmaps->get_rect();
	rect += (parent->get_client_rect().size() - rect.size()) / 2;
	init( rect );

	// create backgrounds
	t_bitmap_layer const* layer;
	t_window*             background;
	t_screen_point		  origin(0,0);

	layer = m_bitmaps->find( "background" );
	background = new t_bitmap_layer_window( layer, origin, this );
	origin = layer->get_rect().top_left();

	// create title
	rect = m_bitmaps->find( "title" )->get_rect() - origin;
	m_title = new t_text_window( get_font( rect.height() ), rect, background, "",
		                         t_pixel_24(0,0,0));
	m_title->set_drop_shadow( false );
	m_title->set_center_horizontal();

	// create text
	rect = m_bitmaps->find( "text" )->get_rect() - origin;
	m_text = new t_text_window( get_font( 20 ), rect, background, "", t_pixel_24(0,0,0));
	m_text->set_drop_shadow( false );
	m_text->set_center_horizontal();

	// create buttons
	t_button*        button;
	t_button_handler handler;

	m_enter_button = create_button( m_bitmaps, "enter", background, origin );
	handler = add_2nd_argument( bound_handler( *this, &t_dialog_sanctuary::close_click ),
		                        int( k_choice_enter ));
	m_enter_button->set_click_handler( handler );

	rect = m_bitmaps->find( "close_button" )->get_rect() - origin;
	button = new t_button( k_close_button.get(), rect.top_left(), background );
	handler = add_2nd_argument( bound_handler( *this, &t_dialog_sanctuary::close_click ),
		                        int( k_choice_cancel ));
	button->set_click_handler( handler );	

	// create labels
	t_text_window* text_window;

	rect = m_bitmaps->find( "enter_text" )->get_rect() - origin;
	text_window = new t_text_window( get_font( rect.height() / 2 ), rect, background,
		                             k_text_entry_label, t_pixel_24(0,0,0));
	text_window->set_drop_shadow( false );
	text_window->set_center_horizontal();
}

// ------------------------------------------------------------------------
// sanctuary dialog
// ------------------------------------------------------------------------
void t_dialog_sanctuary::enable_entry( bool arg )
{
	m_enter_button->enable( arg );
}
// ------------------------------------------------------------------------
// sanctuary dialog
// ------------------------------------------------------------------------
void t_dialog_sanctuary::set_text( std::string const& text )
{
	m_text->set_text( text );
}

// ------------------------------------------------------------------------
// sanctuary dialog
// ------------------------------------------------------------------------
void t_dialog_sanctuary::set_title( std::string const& title )
{
	m_title->set_text( title );
}

// ------------------------------------------------------------------------
// sanctuary dialog
// ------------------------------------------------------------------------
void t_dialog_sanctuary::close_click( t_button* button, int value )
{
	m_return_value = value;
	close();
}

/*
** Sea sanctuary (port)
*/
t_sea_sanctuary::t_sea_sanctuary( std::string const& source )
        : t_sanctuary( source )
{
}

bool t_sea_sanctuary::is_triggered_by( t_creature_array const& army ) const
{
	return true;
}

void t_sea_sanctuary::dump_visitors()
{
	t_adv_map_point point;

	t_army_ptr boat;

	boat = new t_army( this );
	boat->set_boat_type( boat->get_creatures().get_leader().get_alignment() );
	boat->set_owner( get_owner_number() );

	if (!find_adjacent_space( point, *boat ))
		return;
	
	boat->place( *m_map, point );
	set_owner( -1 );
	get_adventure_frame()->select_army( boat );
	get_adventure_frame()->update();
	boat->trigger_events();
}

